package com.excilys.capicsoubank.dao.impl;

import java.util.List;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.stereotype.Repository;

import com.excilys.capicsoubank.dao.TransactionDao;
import com.excilys.capicsoubank.entities.Account;
import com.excilys.capicsoubank.entities.Transaction;
import com.excilys.capicsoubank.entities.TransactionType;

/**
 * @author Sébastien Bihan
 * 
 */
@Repository
public class TransactionDaoImpl extends GenericDaoImpl<Transaction> implements
		TransactionDao {

	public TransactionDaoImpl() {
		super(Transaction.class);
	}

	private final DateTimeFormatter fmt = DateTimeFormat
			.forPattern("yyyy-MM-dd'T'HH:mm:ss");

	@Override
	public long getSumTransactionsByPeriodByType(Account account,
			DateTime startDate, DateTime endDate, TransactionType[] types) {

		String query = "select sum(amount) from Transaction where date between :firstDayOfMonth and :lastDayOfMonth and account = :account and transactionType in :types";

		Object result = getCurrentSession().createQuery(query)
				.setString("firstDayOfMonth", startDate.toString(fmt))
				.setString("lastDayOfMonth", endDate.toString(fmt))
				.setEntity("account", account).setParameterList("types", types)
				.uniqueResult();

		if (result == null)
			return 0L;

		return (Long) result;

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Transaction> getTransactionByAccountByPeriodByTypeWithPagination(
			Account account, DateTime startDate, DateTime endDate,
			TransactionType[] types, int resultSize, int offset) {

		String query = "from Transaction where account = :account and date between :startDate and :endDate and transactionType in :types order by date desc";
		return getCurrentSession().createQuery(query)
				.setEntity("account", account)
				.setString("startDate", startDate.toString(fmt))
				.setString("endDate", endDate.toString(fmt))
				.setParameterList("types", types).setMaxResults(resultSize)
				.setFirstResult(offset).list();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Transaction> getTransactionByAccountByYearByMonthByType(
			Account account, DateTime startDate, DateTime endDate,
			TransactionType[] types) {

		String query = "from Transaction where account = :account and date between :startDate and :endDate and transactionType in :types";

		return getCurrentSession().createQuery(query)
				.setEntity("account", account)
				.setString("startDate", startDate.toString(fmt))
				.setString("endDate", endDate.toString(fmt))
				.setParameterList("types", types).list();
	}

	@Override
	public Long getCountTransactionByAccountByPeriodByType(Account account,
			DateTime startDate, DateTime endDate, TransactionType[] types) {

		String query = "select count(*) from Transaction where account = :account and date >= :startDate and date <= :endDate and transactionType in :types";

		Object result = getCurrentSession().createQuery(query)
				.setEntity("account", account)
				.setString("startDate", startDate.toString(fmt))
				.setString("endDate", endDate.toString(fmt))
				.setParameterList("types", types).uniqueResult();

		if (result == null)
			return 0L;

		return (Long) result;
	}
}
